package com.atguigu.yygh.user.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.exphandler.YyghException;
import com.atguigu.utils.HttpUtils;
import com.atguigu.utils.JwtHelper;
import com.atguigu.yygh.enums.AuthStatusEnum;
import com.atguigu.yygh.model.user.Patient;
import com.atguigu.yygh.model.user.UserInfo;
import com.atguigu.yygh.user.mapper.UserInfoMapper;
import com.atguigu.yygh.user.service.PatientService;
import com.atguigu.yygh.user.service.UserInfoService;
import com.atguigu.yygh.user.util.AuthContextHolder;
import com.atguigu.yygh.vo.user.LoginVo;
import com.atguigu.yygh.vo.user.UserAuthVo;
import com.atguigu.yygh.vo.user.UserInfoQueryVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author xueyoupeng
 * @since 2023-06-12
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    PatientService patientService;

    @Override
    public Map<String, Object> login(LoginVo loginVo) {
        //需求：openid为空，手机号+验证码登录 ； 不为空，微信绑定手机号
        String openid = loginVo.getOpenid();
        //直接手机号+验证码登录
        if (StringUtils.isEmpty(openid)){
            return this.phoneLogin(loginVo);
        }else {
            //为刚才微信扫码的用户，进行绑定手机号
            //绑定手机号的需求
            return this.bundlePhone(loginVo);
        }
    }

    private Map<String, Object> bundlePhone(LoginVo loginVo) {
        //1.必要的参数非空校验(手机号和验证码)
        String phone = loginVo.getPhone();
        String code = loginVo.getCode();
        if (StringUtils.isEmpty(phone)) {
            throw new YyghException(20001,"手机号为空");
        }
        if (StringUtils.isEmpty(code)) {
            throw new YyghException(20001,"验证码为空");
        }
        //2.校验--短信验证码 失败--》抛出异常 phone是key code是value
        String codeFromRedis = redisTemplate.opsForValue().get(phone);
        if (StringUtils.isEmpty(codeFromRedis)){
            throw new YyghException(20001,"验证码不存在,请重新发送");
        }

        //3.根据openid查询用户,根据phone查询用户,判断接下来是否需要涉及到数据合并
        UserInfo userInfoByOpenId = this.selectByOpenId(loginVo.getOpenid());
        UserInfo userInfoByPhone = this.selectByPhone(phone);

        //4.判断userInfoByPhone是否为空
        if (userInfoByPhone==null){
            //此手机号从未使用过 直接把phone赋值给userInfoByOpenId
            userInfoByOpenId.setPhone(phone);
            //根据openid进行更新
            baseMapper.updateById(userInfoByOpenId);
            return this.getMap(userInfoByOpenId);
        }else {
            //判断该手机号是否已经被某微信绑定
            if(!StringUtils.isEmpty(userInfoByPhone.getOpenid())){
                throw new YyghException(20001,"手机号已经被绑定，请更换手机号");
            }

            //手机号已经存在，将userInfoByOpenId中的openid和nickname
            // 赋值给userInfoByPhone，删除userInfoByOpenId，更新userInfoByPhone
            userInfoByPhone.setOpenid(userInfoByOpenId.getOpenid());
            userInfoByPhone.setNickName(userInfoByOpenId.getNickName());

            //删除的是当前扫码的微信
            baseMapper.deleteById(userInfoByOpenId.getId());
            baseMapper.updateById(userInfoByPhone);

            return this.getMap(userInfoByPhone);
        }
    }

    //封装map=name+token
    private Map<String, Object> getMap(UserInfo userInfo) {
        //优先userInfo中的name属性，其次nickName，最后phone
        String name = "";

        name = userInfo.getName();//真实姓名
        if (StringUtils.isEmpty(name)){
            name = userInfo.getNickName();//微信昵称
            if (StringUtils.isEmpty(name)) {
                name = userInfo.getPhone();//手机号
            }
        }
        String token = JwtHelper.createToken(userInfo.getId(),name);

        Map<String, Object> map = new HashMap<>();
        map.put("name",name);
        map.put("token",token);
        return map;
    }

    private UserInfo selectByPhone(String phone) {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",phone);
        return baseMapper.selectOne(queryWrapper);
    }

    private Map<String,Object> phoneLogin(LoginVo loginVo){
        //输入的手机号
        String phone = loginVo.getPhone();
        //输入的验证码
        String code = loginVo.getCode();
        //判断手机号是否存在
        if (StringUtils.isEmpty(phone)){
            throw new YyghException(20001,"手机号不能为空");
        }
        //判断验证码是否存在
        if (StringUtils.isEmpty(code)){
            throw new YyghException(20001,"验证码不能为空");
        }
        //从redis中获取指定手机号的正确的验证码
        String codeFromRedis = redisTemplate.opsForValue().get(phone);
        if (StringUtils.isEmpty(codeFromRedis)){
            throw new YyghException(20001,"验证码已过期,请重新发送");
        }
        if (!codeFromRedis.equals(code)){
            throw new YyghException(20001,"验证码不正确,请重新输入");
        }
        //判断手机号是否存在
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",phone);
        UserInfo userInfo = baseMapper.selectOne(queryWrapper);
        //手机号不存在，自动注册
        if (userInfo == null) {
            userInfo = new UserInfo();
            userInfo.setPhone(phone);
            userInfo.setAuthStatus(AuthStatusEnum.NO_AUTH.getStatus());//0--未实名认证
            userInfo.setStatus(1);//默认正常状态（0-锁定）

            int insert = baseMapper.insert(userInfo);
            if (insert < 0) {
                throw new YyghException(20001,"自动注册失败");
            }
        }
        //用户被锁定
        if (userInfo.getStatus()==0) {
            throw new YyghException(20001,"用户被锁定");
        }

        String name = "";

        name = userInfo.getName();//真实姓名
        if (StringUtils.isEmpty(name)){
            name = userInfo.getNickName();//微信昵称
            if (StringUtils.isEmpty(name)){
                name = userInfo.getPhone();//手机号
            }
        }
        String token = JwtHelper.createToken(userInfo.getId(),name);

        HashMap<String, Object> map = new HashMap<>();
        map.put("name",name);
        map.put("token",token);//jwt令牌

        return map;
    }

    @Override
    public UserInfo selectByOpenId(String openid) {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("openid",openid);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public UserInfo getUserInfo(HttpServletRequest request) {
        //1、从请求头中获取令牌
//        String token = request.getHeader("token");
        //2、解析令牌，获取userId
//        Long userId = JwtHelper.getUserId(token);
        Long userId = AuthContextHolder.getUserId(request);

        //3、根据userId查询
        UserInfo userInfo = baseMapper.selectById(userId);

        this.packUserInfo(userInfo);//param属性赋值（authStatusString）
        
        return userInfo;
    }

    @Override
    public void userauth(Long userId, UserAuthVo userAuthVo) {
        //1、查询到当前用户
        UserInfo userInfo = baseMapper.selectById(userId);

        //更新认证字段信息
        userInfo.setName(userAuthVo.getName());//用户姓名
        userInfo.setCertificatesType(userAuthVo.getCertificatesType());//证件类型
        userInfo.setCertificatesNo(userAuthVo.getCertificatesNo());//证件编号
        userInfo.setCertificatesUrl(userAuthVo.getCertificatesUrl());//证件路径
        //0改成1，表示已提交，但是还未审核
        userInfo.setAuthStatus(AuthStatusEnum.AUTH_RUN.getStatus());

        //重新为更新时间字段赋值
        userInfo.setUpdateTime(new Date());
        baseMapper.updateById(userInfo);
    }

    @Override
    public Page<UserInfo> selectPage(Integer pageNum, Integer pageSize, UserInfoQueryVo userInfoQueryVo) {
        //分页条件 数据库从1开始 mogoDb从0开始
        Page<UserInfo> userInfoPage = new Page<>(pageNum,pageSize);

        //查询条件
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        //根据name(也就是keyword) 开始时间 结束时间 查询
        String keyword = userInfoQueryVo.getKeyword();
        String createTimeBegin = userInfoQueryVo.getCreateTimeBegin();
        String createTimeEnd = userInfoQueryVo.getCreateTimeEnd();
        //根据authStatus查询用户列表 认证状态
        Integer authStatus = userInfoQueryVo.getAuthStatus();

        //必须要判空 否则会出现sql语句查询条件为null的情况
        if (!StringUtils.isEmpty(keyword)){
            queryWrapper.like("name",keyword);
        }
        if (!StringUtils.isEmpty(createTimeBegin)){
            queryWrapper.eq("create_time",createTimeBegin);
        }
        if (!StringUtils.isEmpty(createTimeEnd)){
            queryWrapper.eq("create_time",createTimeEnd);
        }
        if (!StringUtils.isEmpty(authStatus)){
            queryWrapper.eq("auth_status",authStatus);
        }

        //俩条件 分页 和 查询条件
        Page<UserInfo> selectPage = baseMapper.selectPage(userInfoPage, queryWrapper);

        selectPage.getRecords().forEach(userInfo -> {
            this.packUserInfo(userInfo);
        });
        return selectPage;
    }

    @Override
    public void updateStatus(Long userId, Integer status) {
        //先根据id查询到这条数据
        UserInfo userInfo = baseMapper.selectById(userId);
        userInfo.setStatus(status);//重新设置status
        //重新设置更新时间
        userInfo.setUpdateTime(new Date());
        //更新这条数据
        baseMapper.updateById(userInfo);
    }

    @Override
    public Map<String, Object> show(Long userId) {
        //两部分
        //一部分是userinfo
        UserInfo userInfo = baseMapper.selectById(userId);

        //一部分是就诊人 patient
        List<Patient> patientList = patientService.findAllByUserId(userId);

        HashMap<String, Object> map = new HashMap<>();
        map.put("userInfo",userInfo);
        map.put("patientList",patientList);

        return map;
    }

    @Override
    public void authUser(Long userId, Integer authStatus) {
        UserInfo userInfo = baseMapper.selectById(userId);
        userInfo.setAuthStatus(authStatus);
        userInfo.setUpdateTime(new Date());
        baseMapper.updateById(userInfo);
    }

    @Override
    public Boolean check(String name, String idCard) {
        String host = "http://checkone.market.alicloudapi.com";
        String path = "/chinadatapay/1882";
        String method = "POST";

        String appcode = "1d57485f507e4f0291625fffb907c399";
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();

        bodys.put("idcard",idCard);
        bodys.put("name", name);


        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            System.out.println(response.toString());
            //获取response的body

            String s = EntityUtils.toString(response.getEntity());//{"code":"10000","message":"成功","data":{"result":"2"},"seqNo":"8X657JC5230616115138297"}
            JSONObject jsonObject = JSON.parseObject(s);
            String code = jsonObject.getString("code");
            if ("10000".equals(code)){
                JSONObject data = jsonObject.getJSONObject("data");
                String result = data.getString("result");
                if("1".equals(result)){
                    return true;//姓名和身份证号验证通过
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    private void packUserInfo(UserInfo userInfo) {
        Integer authStatus = userInfo.getAuthStatus();
        String authStatusString = AuthStatusEnum.getStatusNameByStatus(authStatus);

        //用户实名认证审核状态
        userInfo.getParam().put("authStatusString",authStatusString);
    }


}



















